from django.shortcuts import render,redirect
#导包
from django.http import HttpResponse,HttpResponseRedirect,JsonResponse
#导入类视图
from django.views import View

from myapp.models import User,Goods,Comment,UserFollow
import json
from django.core.serializers import serialize
from rest_framework.response import Response
from rest_framework.views import APIView
#导入加密库
import hashlib
#导入图片库
#绘画库
from PIL import ImageDraw
#字体库
from PIL import ImageFont
#图片库
from PIL import Image
#随机库
import random
#文件流
import io

import requests

#导入上传文件夹配置
from mydjango.settings import UPLOAD_ROOT
import os

#导入原生sql模块
from django.db import connection

import jwt

#导入redis数据库
import redis

#导入时间模块
import time

#导入公共目录变量
from mydjango.settings import BASE_DIR

#导包
from django.db.models import Q,F

#导入dwebsocket的库
from dwebsocket.decorators import accept_websocket
import uuid

#导入序列化对象
from myapp.myser import UserSer,GoodsSer,CommentSer

from pymongo import  MongoClient

mongocli = MongoClient(host='localhost',port=27017)

#导入bson
from bson import json_util as jsonb

#定义地址和端口
host = '127.0.0.1'
port = 6379

#建立redis连接
r = redis.Redis(host=host,port=port)

#商品检索接口
class GoodsSearch(APIView):
    def get(self,request):
        #接受参数
        word = request.GET.get("word",None)
        #模拟检索/检索内容使用q查找
        #翻译sql  select * from goods where (name like "%word%" or desc like "%word%")
        #and (parms like "%word%")
        goodslist = Goods.objects.filter(Q(name__contains=word) | Q(desc__icontains=word))
        # goodslist = Goods.objects.filter(name__icontains=word)
        #序列化
        goods_ser = GoodsSer(goodslist,many=True)
        return Response(goods_ser.data)

#工具方法，获取前n名的数据
def get_top_n(num):
    #获取redis的排行榜
    goodsclick = r.zrange('good_rank',0,-1,desc=True,withscores=True)[:num]

    #获取mysql中的数据
    goods = Goods.objects.in_bulk([int(item[0]) for item in goodsclick])

    #合并操作
    res = []
    for item in goodsclick:
        #遍历列表
        try:#为了防止redis和mysql数据不同步
            res.append({int(item[1]):goods[int(item[0])]})
        except Exception as e:
            pass
    return res

#新的商品参与排名
class GoodsClick(APIView):
    def get(self,request):
        #接受参数,作为排行榜商品品名
        id = request.GET.get('id',None)
        #修改商品点击数
        r.zincrby("good_rank",1,int(id))
        #测试查看排行
        print(get_top_n(10))

        return Response({"message":"访问加1"})

#商品排行榜数据视图
class GoodRank(APIView):
    def get(self,request):
        #获取排名前n数据
        get_res = get_top_n(10)

        res = []
        #遍历进行序列化
        for dic in get_res:
            for k,v in dic.items():
                #序列化
                data = GoodsSer(v).data
                #将商品点击数附加到商品的序列化的数据中
                data['clicks'] = k
                res.append(data)

        #返回
        return Response(res)

#sql查询结果集美化方法
def dictfetchall(cursor):
    #获取游标描述
    desc = cursor.description
    return [
        dict(zip(  [col[0] for col in desc ],row ))
        for row in cursor.fetchall()
    ]


#商品被多少人关注(包含取关）
class GoodFollow(APIView):
    def get(self,request):
        gid = request.GET.get("gid")
        uid = request.GET.get("uid")
        #查看是否关注，默认关注
        type = request.GET.get('type',1)
        resp = {}
        if int(type)==1:
            #关注
            userfollow = UserFollow(gid = int(gid),uid=int(uid))

            try:
                userfollow.save()
                resp['message'] = '关注成功'
                goods = Goods.objects.filter(id=int(gid)).first()
                goods.flow = goods.flow +1
                goods.save()
                resp['code'] = 200
            except Exception as e:
                print(e)
                resp['message'] = '不能重复关注'
                resp['code'] = 403
        elif int(type)==0:
            #单独取关
            #首先查询是否关注
            userfollow = UserFollow.objects.filter(gid=int(gid), uid=int(uid))
            if userfollow:
                UserFollow.objects.filter(gid=int(gid),uid=int(uid)).delete()
                resp['message'] = '取关成功'
                goods = Goods.objects.filter(id=int(gid)).first()
                goods.flow -= 1
                goods.save()
                resp['code'] = 200
            else:
                resp['message'] = "错误操作！"
                resp['code'] = 405
        else:
            #批量取关
            ids = request.GET.get('ids',None)
            #批量操作
            UserFollow.objects.filter(uid=int(uid)).delete()
            #强转 eval字符串语义化
            id_list = eval(ids)
            for id in id_list:
                userfollow = UserFollow(gid=int(id),uid=int(uid))
                userfollow.save()

            resp['message'] = '批量关注成功'


        # 建立游标对象
        cursor = connection.cursor()
        # 执行sql语句
        cursor.execute(
            'SELECT a.username FROM user a LEFT JOIN userfollow b ON b.uid = a.id WHERE gid = %s' % str(gid))
        result_user = dictfetchall(cursor)
        resp['data'] = result_user

        return Response(resp)


#商品关注（查询用户关注过的商品列表）
class UidFollow(View):
    def get(self,request):
        uid = request.GET.get("uid")
        #建立游标对象
        cursor = connection.cursor()
        #执行sql语句
        cursor.execute('SELECT a.id,a.name,a.create_time FROM goods a left join userfollow b on a.id=b.gid  where uid=%s'%str(uid))
        result = dictfetchall(cursor)
        #返回结果
        return HttpResponse(json.dumps(result,ensure_ascii=False,indent=4,default=str),content_type='application/json')

#用户列表
class UserList(APIView):
    def get(self,request):
        #查询所有用户
        user = User.objects.all()
        user_ser = UserSer(user,many=True)
        return Response(user_ser.data)


#评论展示列表
class CommentList(APIView):
    def get(self,request):
        id = request.GET.get("id",None)
        #排序展示最新评论
        comments = Comment.objects.filter(gid=int(id)).order_by('-id')
        commentsser = CommentSer(comments,many=True).data
        return Response({"data":commentsser})



#反序列化入库(评论）
class InsertComment(APIView):
    def post(self,request):
        dict1 = dict(request.data)
        print(dict1['uid'][0],dict1['content'][0])
        uid = request.POST.get("uid",None)
        #初始化参数
        comment = CommentSer(data=request.data)
        #数据校验、数据入库
        #校验数据正确性
        if r.get(str(uid)):
            return Response({'code':403,"message":'您评论的太快了，请歇一歇'})

        if comment.is_valid():
            #数据入库
            # comment.create(comment.data)
            #解决时间入库问题
            comment.save()

            #插入时间设置
            r.set(str(uid),'123')
            r.expire(str(uid),30)

        # 建立数据库对象
        db = mongocli.mdshop
        # 建立表对象
        table = db.mycomment
        table.insert({'uid': int(dict1['uid'][0]), 'comment': dict1['content'][0]})

        return Response({'code':200,"message":"评论成功！"})




#统计在线人数
class GetOnLine(APIView):
    def get(self,request):
        #获取客户端IP
        if 'HTTP_X_FORWARDED_FOR' in request.META:
            ip = request.META.get("HTTP_X_FORWARDED_FOR")
        else:
            ip = request.META.get("REMOTE_ADDR")

        r.sadd('online',ip)

        #设置超时时间,超时时长（单位:s）
        r.expire('online',20)

        #获取在线人数数量
        myset = r.smembers('online')

        return Response({"online":len(myset)})





#更新商品标签
class UpdateTags(APIView):
    def get(self,request):
        id = request.GET.get('id',None)
        tags = request.GET.get('tags',None)
        tags = tags.split(",")
        #建立数据库对象
        db = mongocli.mdshop
        #建立表对象
        table = db.mytag

        # 排重,商品id不能重复
        res = table.find({'gid': str(id)}).count()
        if res > 0:
            table.update({'gid': str(id)}, {"$set":{'tags': tags}})
            return Response({'message': '入库成功'})

#获取商品标签
class GetTags(View):
    def get(self,request):
        id = request.GET.get("id",None)
        # 建立数据库对象
        db = mongocli.mdshop
        # 建立表对象
        table = db.mytag

        #查询数据
        res = table.find_one({"gid":str(id)})
        return HttpResponse(jsonb.dumps(res,ensure_ascii=False))

#添加商品标签
class InsertTags(APIView):
    def get(self,request):
        id = request.GET.get('id',None)
        tags = request.GET.get('tags',None)
        tags = tags.split(",")

        # print(tags)
        #列表转回字符串(同时解决列表中含有int型数据的问题)
        # tags = ','.join(['%s' % tag for tag in tags])
        #建立数据库对象
        db = mongocli.mdshop
        #建立表对象
        table = db.mytag

        #再存入redis一份
        for i in range(len(tags)):
            # print(tags[i])
            r.sadd('testset', str(tags[i]))
        redis_set = r.smembers('testset')

        #排重,商品id不能重复
        res = table.find({'gid':str(id)}).count()
        if res >0:
            return Response({"message":'重复数据！'})
        else:
            table.insert({'gid':str(id),'tags':tags})
            return Response({'message':'入库成功'})


#商品分类接口
class CategoryInfo(APIView):

    def get(self,request):
        pass
        #进行商品查询
        # category = Category.objects.filter()

        #进行序列化操作
        # cate_ser = CategorySer(category,many=True)

        #进行返回
        # return Response(cate_ser.data)

#商品更新接口
class UpdateGoods(APIView):
    def get(self,request):
        name = request.GET.get('name','null')
        desc = request.GET.get('desc','null')
        print(desc)
        parms = request.GET.get('parms','null')
        price = request.GET.get('price','null')

        #排重
        good = Goods.objects.filter(name=name).first()
        #进行入库
        good.name = name
        good.desc = desc
        good.parms = parms
        good.price = price

        good.save()

        res = {}
        res['code'] = 200
        res['id'] = good.id
        res['message'] = '商品更新成功'

        return Response(res)

#商品入库接口
class AddGoods(APIView):
    def get(self,request):
        name = request.GET.get('name','null')
        desc = request.GET.get('desc','null')
        parms = request.GET.get('parms','null')
        cate_id = request.GET.get('cate_id','null')
        price = request.GET.get('price','null')

        #排重
        goods = Goods.objects.filter(name=name).first()

        if goods:
            res = {}
            res['code'] = 405
            res['message'] = '该商品已经存在'
            return Response(res)

        #进行入库
        goods = Goods(name=name,desc=desc,
                      parms=parms,cate_id=cate_id,price=price)
        goods.save()

        res = {}
        res['code'] = 200
        res['id'] = goods.id
        res['message'] = '商品添加成功'

        return Response(res)

#商品列表接口
class GoodsList(APIView):

    def get(self,request):
        #当前页
        page = int(request.GET.get('page',1))
        #一页有多少条商品
        size = int(request.GET.get('size',1))
        #从哪开始切
        data_start = (page-1) * size
        #定义切到哪
        data_end = page * size
        #查询数据
        goodslist = Goods.objects.all()[data_start:data_end]
        #查询总数——count返回整形的数量
        count = Goods.objects.count()
        #序列化
        goods_ser = GoodsSer(goodslist,many=True)
        res = {
            'total':count,
            'data':goods_ser.data
        }
        return Response(res)

#商品详情
class GoodItem(APIView):
    def get(self,request):
        gid = request.GET.get("gid")

        good = Goods.objects.filter(id=gid).first()
        resp = {}
        resp['code'] = 200
        resp['message'] = '商品获取成功。'
        resp['data'] = GoodsSer(good).data

        return Response(resp)


